package com.securecrt;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.regex.Pattern;


import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpATTRS;
import com.jcraft.jsch.SftpException;
import com.jcraft.jsch.UserInfo;

import android.graphics.Color;
import android.text.SpannableString;
import android.text.style.BackgroundColorSpan;
import android.text.style.UnderlineSpan;
import android.util.Log;

public class SSHClient {

    /** Channel modes */
    public static final String  EXEC_MODE               = "exec";

    public static final String  SHELL_MODE              = "shell";

    public static final String  SFTP_MODE               = "sftp";

    /** Authentication */
    private static String       USER;

    private static String       PWD;

    private static String       HOST;
    
    private static int       	PORT;
    
    private static String       CIPHER;
    
    private static String       MAC;

    /** Utils */
    private String              CMD_INVITE;

    private PipedInputStream    fromServer;

    private OutputStream        toServer;

    private Channel             channel;

    private Session             session;

    private static final String TERMINATOR              = "zDonez";

    private String              lastCommand             = "";

    private Pattern             alphaNumeric            = Pattern.compile("([^a-zA-z0-9])");

    private int                 nbChannel               = 0;

    private String              previousMode;

    private int                 SERVER_RESPONSE_TIMEOUT = 1000;
    
    static final int 			DEFAULT_BUFFER_SIZE = 4096;

    /** Low-level layer to provide ssh functions */
    private SCP                 scp;

    /** Shell */
    private JSch                shell;
    
    private String 				head = "";
    private String 				path = "";

	public SSHClient(String user, String pass, String host, int port, String cipher, String mac) throws Exception {
        shell = new JSch();
        USER = user;
        PWD = pass;
        HOST = host;
        PORT = port;
        CIPHER = cipher;
    	MAC = mac;
        CMD_INVITE = HOST + ":" + USER + "#";
        initSession();
        
     
    }
    
    /**
     * Init SSH session
     * @throws Exception 
     * @throws JSchException
     */
    void initSession() throws Exception {
        try {
        	if(PORT<=0){
        		session = shell.getSession(USER, HOST);
        	}else{
        		session = shell.getSession(USER, HOST, PORT);
        	}
            if(PWD!=null||"".equals(PWD)){
	            MyUserInfo ui = new MyUserInfo();
	            ui.setPassword(PWD);
	            session.setUserInfo(ui);
            }
            Properties config = new Properties();
            if(CIPHER != null && !CIPHER.equals("none")){
	            config.put("cipher.s2c", CIPHER); 
	            config.put("cipher.c2s", CIPHER);
	            session.setConfig("CheckCiphers", CIPHER);
            }
            if(MAC != null && !MAC.equals("none")){
	            config.put("mac.s2c", MAC);
	            config.put("mac.c2s", MAC);
            }
            
            config.put("3des-cbc","com.jcraft.jsch.jce.TripleDESCBC");
            config.put("aes128-cbc", "com.jcraft.jsch.jce.AES128CBC");
            config.put("blowfish-cbc","com.jcraft.jsch.jce.BlowfishCBC");
            config.put("hmac-sha1","com.jcraft.jsch.jce.HMACSHA1");
            config.put("hmac-md5","com.jcraft.jsch.jce.HMACMD5");
            config.put("StrictHostKeyChecking", "no");
            session.setConfig(config);

            session.connect();
            //session.connect(30000); // making a connection with timeout.
            scp = new SCP(session);
            String pwd = sendShell("pwd -P");
            path = "~";
            head = collapseNewlines(pwd.substring(pwd.indexOf("[")-1,pwd.indexOf("~"))+" ");
        } catch (JSchException e) {
            e.printStackTrace();
            Log.d("sshAndroid.Connection.Exec", e.getMessage());
            throw new Exception(e.getLocalizedMessage());
        }
    }

    /**
     * Connects to remote machine
     * @param mode Type of channel to open : can be EXEC_MODE, SHELL_MODE, SFTP_MODE
     * @throws Exception 
     * @throws JSchException
     * @throws IOException
     * @throws InterruptedException
     */
    private void connect(String mode) throws Exception {

        if (!isConnected()) {
            try {
                channel = session.openChannel(mode);
                previousMode = mode;
                // If Shell mode, customize I/O streams to get response
                if (mode.equals(SHELL_MODE)) {
                    initShellMode();
                    channel.connect();
                }
            } catch (Exception e) {
                e.printStackTrace();
                Log.d("sshAndroid.Connection.Exec", e.getMessage());
                throw new Exception(e.getLocalizedMessage());
            }
        
        } else {
//            // To avoid 10 files upload limitation in session
////            if (nbChannel == 9) {
////                disconnect();
////                nbChannel = 0;
////                connect(mode);
////            }
            // Change channel
            if (!previousMode.equals(mode)) {
                previousMode = mode;
                channel.disconnect();
                connect(mode);
            }
            nbChannel++;
        }
    }

    /**
     * Init shell mode
     * @throws IOException
     */
    private void initShellMode() throws IOException {
        PipedOutputStream po = new PipedOutputStream();
        fromServer = new PipedInputStream(po);
        channel.setOutputStream(po);

        toServer = new PipedOutputStream();
        PipedInputStream pi = new PipedInputStream((PipedOutputStream) toServer);
        channel.setInputStream(pi);
    }

    /**
     * Check if client is connected
     * @return YES or NO
     */
    public boolean isConnected() {
        return (channel != null && channel.isConnected());
    }

    /**
     * Disconnect channel and session
     */
    public void disconnect() {
        if (isConnected()) {
            channel.disconnect();
            session.disconnect();
        }
    }

    /**
     * Disconnect client and open new session
     * @throws Exception 
     */
    public void reconnect() throws Exception {
        disconnect();
        initSession();
    }

    /**
     * Send simple SHELL command
     * @param command
     * @return server response
     * @throws Exception 
     * @throws IOException
     * @throws InterruptedException
     */
    public String sendShell(String command) throws Exception {
        connect(SHELL_MODE);
        lastCommand = command;
        command += "; echo \"" + TERMINATOR + "\" \n";
        try {
            toServer.write(command.getBytes());
            // To ensure server answer reception
            // and manage a communication time out.
            try {
                Thread.sleep(SERVER_RESPONSE_TIMEOUT);
            } catch (InterruptedException e) {
            }
        } catch (IOException e) {
            e.printStackTrace();
             Log.d("sshAndroid.Connection.Exec", e.getMessage());
            throw new Exception(e.getLocalizedMessage());
        }
       
        return getServerResponse();
    }
    
  
    
    private String RemoveJunk(String str)
	{
    	String[] junk = new String[]{"[00m[01;34m","[01;35m","[01;31m","[01;32m","[01;34m","[00m","[m","[00m","[132;1H", "[24;1H", 
    									"[K", "[7m",""," \b", "--More--", "\r", "\n   "};
         
         for( int i=0; i<junk.length; i++ )
         {
                 String match = junk[i];
                 if (match.equalsIgnoreCase("\n   "))
                         str = str.replace(match, "\n");
                 else
                         str = str.replace(match, "\u0020");
 
         }
    	return str;
	}
    
    /**
     * Retrieve server response to SHELL command
     * @return the response
     * @throws Exception 
     * @throws IOException
     * @throws InterruptedException
     */
    private String getServerResponse() throws Exception {
        StringBuffer builder = new StringBuffer();
        String result = null;
        try {
            int count = 0;
            String line = "";            

            BufferedReader reader = new BufferedReader(new InputStreamReader(fromServer,"UTF-8"),DEFAULT_BUFFER_SIZE);
            if (reader.ready()) {
            	//while ((line = reader.readLine()) != null) {
            	for (int i = 0; true; i++) {  
            		try {  
            			line = reader.readLine();          			          		               			 	
            		} catch (Exception e) {  
            			  Log.d("sshAndroid.Connection.Exec","Communication seems to be closed...");  
            		      break;  
            		}                 
            		line = RemoveJunk(line); 
             		SpannableString content = new SpannableString(line);
                    content.setSpan(new BackgroundColorSpan(Color.YELLOW), 0, line.length(), 0);
                    builder.append(content).append("\n");              			
                    if (line.indexOf(TERMINATOR) != -1 && (++count > 1)) {
                        break;
                    }
                }
                
                result = builder.toString();
                result = new String(result.getBytes(), "UTF-8");
                if(!lastCommand.equals("pwd -P")){
	                int beginIndex = result.indexOf(TERMINATOR + "\"")
	                    + ((TERMINATOR + "\"").length());
	                result = result.substring(beginIndex);
                }
                result = result.replaceAll(escape(TERMINATOR), "").trim();
                //System.out.println("Command : " + lastCommand + " -> Result : " + result);             
                                
                //Change current dir
                final String[] cmds = lastCommand.split(" ");
                final String cmd = cmds[0];
                if(cmd.equals("cd")){
        	        String pwd = sendShell("pwd -P");
        	        path = "/"+pwd.substring(pwd.lastIndexOf("/")+1,pwd.length());
        	        lastCommand="";
                }//end ---------                
                               
                return collapseNewlines(head+path+"]$ "+lastCommand+"\n" + result);
            } else {
                throw new Exception("Server did not answer in the time ("
                    + SERVER_RESPONSE_TIMEOUT + "ms) to command ("
                    + lastCommand + ")");
            }
        } catch (IOException e) {
            e.printStackTrace();
             Log.d("sshAndroid.Connection.Exec", e.getMessage());
            throw new Exception(e.getLocalizedMessage());
        } finally{
        	 //Get current directory
            
		}  
    }

    private String escape(String subjectString) {
        return alphaNumeric.matcher(subjectString).replaceAll("\\\\$1");
    }

    /**
     * Remove/collapse multiple newline characters.
     *
     * @param argStr string to collapse newlines in.
     * @return String
     */
    public static String collapseNewlines(String argStr)
    {
        char last = argStr.charAt(0);
        StringBuffer argBuf = new StringBuffer();

        for (int cIdx = 0 ; cIdx < argStr.length(); cIdx++)
        {
            char ch = argStr.charAt(cIdx);
            if (ch != '\n' || last != '\n')
            {
                argBuf.append(ch);
                last = ch;
            }
        }

        return argBuf.toString();
    }
    
      
    public String execCommand(String command) throws JSchException, Exception{
    	connect(EXEC_MODE);
    	String output="";
    	lastCommand = command;
		try{  
			channel = session.openChannel(EXEC_MODE);
	        ((ChannelExec) channel).setCommand(command);
	        
	        channel.setXForwarding(true);	
	        
	        channel.setInputStream(null);
	        ((ChannelExec) channel).setErrStream(System.err);
	        
	        OutputStream os = channel.getOutputStream();
	        InputStream in = channel.getInputStream();
	        channel.connect();
	        output = convertInputStreamToString(in);
	        output = new String(output.getBytes(), "UTF-8");
	        os.write("PS1=\"MY_PROMPT>\"".getBytes());
	        os.write("\n".getBytes());
	        os.write("TERM=ansi".getBytes());
	        os.write("\n".getBytes());
	        os.write(command.getBytes());
	        os.write("\n".getBytes());
	        os.flush();
	        in.close();
	        channel.disconnect();
		}catch(Exception e){   
		       e.printStackTrace();  
		}
		
		 return collapseNewlines(head+path+"]$ "+lastCommand+"\n"+output);
	}
    
    private String setInAndOutStream(Channel channel, InputStream in) throws IOException, JSchException {
        
        int count = 0;

		StringBuilder commandOutPut = new StringBuilder();

		byte[] tmp = new byte[1024];
		while (true) {
			while (in.available() > 0) {
				int i = in.read(tmp, 0, 1024);
				if (i < 0)
					break;
				//System.out.print(new String(tmp, 0, i));
				commandOutPut.append(new String(tmp, 0, i));
			}

			if (channel.isClosed()) {
				System.out.println("exit-status: " + channel.getExitStatus());
				break;
			}
			try {
				Thread.sleep(1000);
			} catch (Exception ee) {
				ee.printStackTrace();
			}
			++count;
			System.out.println("Wainting..." + count);

		}
				

        return commandOutPut.toString();
    }

    public String convertInputStreamToString(InputStream in) {
        StringBuffer sb = new StringBuffer();
        try {
             InputStreamReader isr = new InputStreamReader(in,"ISO-8859-1");
             Reader reader = new BufferedReader(isr,DEFAULT_BUFFER_SIZE);
             int ch;
             while(true){  
	             while ((ch = in.read()) > -1) {
	                  sb.append((char) ch);
	             }
	             if(channel.isClosed()){                 
					System.out.println("exit-status: "+channel.getExitStatus());     
					Log.d("sshAndroid.Connection.Exec", "exit-status: " + channel.getExitStatus());
					break;               
				}               
				try{
					Thread.sleep(SERVER_RESPONSE_TIMEOUT);
				}catch(Exception ee){		}        
             }
             reader.close();
        } catch (Exception exception) {

        }
        return sb.toString();

   }
 
          
    public String execSftp(final String command) throws Exception{
    	lastCommand = command;
    	connect(SFTP_MODE);
    	StringBuilder outPutResult = new StringBuilder("");
    	//Channel channel=session.openChannel("sftp");
        channel.connect();
        ChannelSftp cSftp=(ChannelSftp)channel;
        final String[] cmds = command.split(" ");
        final String cmd = cmds[0];

        if (cmd.equals("quit")) {
        	cSftp.quit();
        } else if (cmd.equals("exit")) {
        	cSftp.exit();
        } else if (cmd.equals("rekey")) {
            try {
                session.rekey();
            } catch (final Exception e) {
                //err.println(e);
            	Log.d("adroid.Connection.Sftp", e.getMessage());
            }
        } else if (cmd.equals("cd") || cmd.equals("lcd")) {
            if (cmds.length != 2) {
                //err.println("Invalid arguments");
            	Log.d("adroid.Connection.Sftp", "Invalid arguments");
                //return;
            }
            final String path = cmds[1];
            try {
                if (cmd.equals("cd")) {
                    cSftp.cd(path);
                } else {
                    cSftp.lcd(path);
                }
            } catch (final SftpException e) {
                //err.println(e);
            	Log.d("adroid.Connection.Sftp", e.getMessage());
            }
        } else if (cmd.equals("rm") || cmd.equals("rmdir")
                || cmd.equals("mkdir")) {
            if (cmds.length != 2) {
                //err.println("Invalid arguments");
            	Log.d("adroid.Connection.Sftp", "Invalid arguments");
                //return;
            }
            final String path = cmds[1];
            try {
                if (cmd.equals("rm")) {
                    cSftp.rm(path);
                } else if (cmd.equals("rmdir")) {
                    cSftp.rmdir(path);
                } else {
                    cSftp.mkdir(path);
                }
            } catch (final SftpException e) {
                //err.println(e);
            	Log.d("adroid.Connection.Sftp", e.getMessage());
            }
        } else if (cmd.equals("chgrp") || cmd.equals("chown")
                || cmd.equals("chmod")) {
            if (cmds.length != 3) {
                //err.println("Invalid arguments");
            	Log.d("adroid.Connection.Sftp", "Invalid arguments");
                //return;
            }
            final String path = cmds[2];
            int foo = 0;
            if (cmd.equals("chmod")) {
                final byte[] bar = cmds[1].getBytes();
                int k;
                for (int j = 0; j < bar.length; j++) {
                    k = bar[j];
                    if (k < '0' || k > '7') {
                        foo = -1;
                        break;
                    }
                    foo <<= 3;
                    foo |= (k - '0');
                }
                if (foo == -1) {
                    throw new Exception();
                }
            } else {
                try {
                    foo = Integer.parseInt(cmds[1]);
                } catch (final Exception e) {
                    throw new Exception(e);
                }
            }
            try {
                if (cmd.equals("chgrp")) {
                    cSftp.chgrp(foo, path);
                } else if (cmd.equals("chown")) {
                    cSftp.chown(foo, path);
                } else if (cmd.equals("chmod")) {
                    cSftp.chmod(foo, path);
                }
            } catch (final SftpException e) {
                //err.println(e);
            	Log.d("adroid.Connection.Sftp", e.getMessage());
            }
        } else if(cmd.equals("pwd") || cmd.equals("lpwd")){
            //String str=(cmd.equals("pwd")?"Remote":"Local");
            //str+=" working directory: ";
        	String str="";
            if(cmd.equals("pwd")) {
                try {
                    str+=cSftp.pwd();
                } catch (final SftpException e) {
                    /*err.println(e);*/
                	Log.d("adroid.Connection.Sftp", e.getMessage());
                }
            } else {
                str+=cSftp.lpwd();
            }
            /*out.println(str);*/
            outPutResult.append(str);
        } else if(cmd.equals("ls") || cmd.equals("dir")){
            String path=".";
            if(cmds.length==2) {
                path=cmds[1];
            }
            try{
                final java.util.Vector<?> vv=cSftp.ls(path);
                if(vv!=null){
                    for(int ii=0; ii<vv.size(); ii++){

                        final Object obj=vv.elementAt(ii);
                        if(obj instanceof com.jcraft.jsch.ChannelSftp.LsEntry){
                            //out.println(((com.jcraft.jsch.ChannelSftp.LsEntry)obj).getLongname());
                        	outPutResult.append(((com.jcraft.jsch.ChannelSftp.LsEntry)obj).getLongname());
                        }

                    }
                }
            } catch(final SftpException e){
                //err.println(e);
            	Log.d("adroid.Connection.Sftp", e.getMessage());
            }
        } else if(cmd.equals("lls") || cmd.equals("ldir")){
            String path=".";
            if(cmds.length==2) {
                path=cmds[1];
            }
            try{
                final java.io.File file=new java.io.File(path);
                if(!file.exists()){
                    //out.println(path+": No such file or directory");
                    outPutResult.append(path+": No such file or directory");
                } else
                    if(file.isDirectory()){
                        final String[] list=file.list();
                        for(int ii=0; ii<list.length; ii++){
                            //out.println(list[ii]);
                        	outPutResult.append(list[ii]);
                        }
                    } else {
                        //out.println(path);
                    	outPutResult.append(path);
                    }
            } catch(final Exception e){
                //err.println(e);
            	Log.d("adroid.Connection.Sftp", e.getMessage());
            }
        } else if(cmd.equals("get") ||
                cmd.equals("get-resume") || cmd.equals("get-append") ||
                cmd.equals("put") ||
                cmd.equals("put-resume") || cmd.equals("put-append")) {
            if(cmds.length!=2 && cmds.length!=3) {
                //err.println("Invalid arguments");
            	Log.d("adroid.Connection.Sftp", "Invalid arguments");
                //return;
            }
            final String p1=cmds[1];
            String p2=".";
            if(cmds.length==3) {
                p2=cmds[2];
            }
            try{
                if(cmd.startsWith("get")){
                    int mode=ChannelSftp.OVERWRITE;
                    if(cmd.equals("get-resume")){ mode=ChannelSftp.RESUME; }
                    else if(cmd.equals("get-append")){ mode=ChannelSftp.APPEND; }
                    cSftp.get(p1, p2, null, mode);
                }
                else{
                    int mode=ChannelSftp.OVERWRITE;
                    if(cmd.equals("put-resume")){ mode=ChannelSftp.RESUME; }
                    else if(cmd.equals("put-append")){ mode=ChannelSftp.APPEND; }
                    cSftp.put(p1, p2, null, mode);
                }
            } catch(final SftpException e){
                //err.println(e);
            	Log.d("adroid.Connection.Sftp", e.getMessage());
            }
        } else if(cmd.equals("ln") || cmd.equals("symlink") || cmd.equals("rename")){
            if(cmds.length!=3) {
                //err.println("Invalid arguments");
                Log.d("adroid.Connection.Sftp", "Invalid arguments");
                //return;
            }
            final String p1=cmds[1];
            final String p2=cmds[2];
            try{
                if(cmd.equals("rename")) {
                    cSftp.rename(p1, p2);
                } else {
                    cSftp.symlink(p1, p2);
                }
            } catch(final SftpException e){
                //err.println(e);
            	Log.d("adroid.Connection.Sftp", e.getMessage());
            }
        } else if(cmd.equals("stat") || cmd.equals("lstat")){
            if(cmds.length!=2) {
                //err.println("Invalid arguments");
            	Log.d("adroid.Connection.Sftp", "Invalid arguments");
                //return;
            }
            final String p1=cmds[1];
            SftpATTRS attrs=null;
            try{
                if(cmd.equals("stat")) {
                    attrs=cSftp.stat(p1);
                } else {
                    attrs=cSftp.lstat(p1);
                }
            }
            catch(final SftpException e){
                //err.println(e);
            	Log.d("adroid.Connection.Sftp", e.getMessage());
            }
            if(attrs!=null){
                //out.println(attrs);
                outPutResult.append(attrs);
            }
        } else if(cmd.equals("readlink")){
            if(cmds.length!=2) {
                //err.println("Invalid arguments");
            	Log.d("adroid.Connection.Sftp", "Invalid arguments");
                //return;
            }
            final String p1= cmds[1];
            String filename=null;
            try{
                filename=cSftp.readlink(p1);
                //out.println(filename);
                outPutResult.append(filename);
            } catch(final SftpException e){
                //err.println(e);
            	Log.d("adroid.Connection.Sftp", e.getMessage());
            }
        } else if(cmd.equals("realpath")){
            if(cmds.length!=2) {
                //err.println("Invalid arguments");
            	Log.d("adroid.Connection.Sftp", "Invalid arguments");
                //return;
            }
            final String p1=cmds[1];
            String filename=null;
            try{
                filename=cSftp.realpath(p1);
                //out.println(filename);
                outPutResult.append(filename);
            } catch(final SftpException e){
                //err.println(e);
            	Log.d("adroid.Connection.Sftp", e.getMessage());
            }
        } else if(cmd.equals("version")){
            //out.println("SFTP protocol version "+cSftp.version());
            outPutResult.append("SFTP protocol version "+cSftp.version());
        } else if(cmd.equals("help") || cmd.equals("?")){
            //out.println(help);
        	outPutResult.append(help);
        } else {
            //err.println("unimplemented command: "+cmd);
        	Log.d("adroid.Connection.Sftp", "unimplemented command: "+cmd);
        }
        return collapseNewlines(head+path+"]$ "+lastCommand+"\n"+outPutResult.toString());
    }

    private static String help =
        "      Available commands:\n"+
        "      * means unimplemented command.\n"+
        "cd path                       Change remote directory to 'path'\n"+
        "lcd path                      Change local directory to 'path'\n"+
        "chgrp grp path                Change group of file 'path' to 'grp'\n"+
        "chmod mode path               Change permissions of file 'path' to 'mode'\n"+
        "chown own path                Change owner of file 'path' to 'own'\n"+
        "help                          Display this help text\n"+
        "get remote-path [local-path]  Download file\n"+
        "get-resume remote-path [local-path]  Resume to download file.\n"+
        "get-append remote-path [local-path]  Append remote file to local file\n"+
        "*lls [ls-options [path]]      Display local directory listing\n"+
        "ln oldpath newpath            Symlink remote file\n"+
        "*lmkdir path                  Create local directory\n"+
        "lpwd                          Print local working directory\n"+
        "ls [path]                     Display remote directory listing\n"+
        "*lumask umask                 Set local umask to 'umask'\n"+
        "mkdir path                    Create remote directory\n"+
        "put local-path [remote-path]  Upload file\n"+
        "put-resume local-path [remote-path]  Resume to upload file\n"+
        "put-append local-path [remote-path]  Append local file to remote file.\n"+
        "pwd                           Display remote working directory\n"+
        "stat path                     Display info about path\n"+
        "exit                          Quit sftp\n"+
        "quit                          Quit sftp\n"+
        "rename oldpath newpath        Rename remote file\n"+
        "rmdir path                    Remove remote directory\n"+
        "rm path                       Delete remote file\n"+
        "symlink oldpath newpath       Symlink remote file\n"+
        "readlink path                 Check the target of a symbolic link\n"+
        "realpath path                 Canonicalize the path\n"+
        "rekey                         Key re-exchanging\n"+
        "compression level             Packet compression will be enabled\n"+
        "version                       Show SFTP version\n"+
        "?                             Synonym for help";
	
    /**
     * getCurrDir: return to current working directory
     * @return
     * @throws IOException
     */
    public String getCurrDir() throws Exception {
        //send command "pwd " to the FTP server
    	return execCommand("pwd");
    }
    
    /**
     * Execute remote script
     * @param scriptPath
     * @throws Exception
     */
    public String executeScript(String scriptPath, String[] params)
        throws Exception {
        String commandLine = scriptPath;
        for (String p : params) {
            commandLine += " " + p;
        }
        return sendShell(commandLine);
    }

    /**
     * Send a file on server (implementation of <code>exec 'scp -t rfile'</code> command)
     * @param localFilePath
     * @param remoteFilePath
     * @throws Exception
     */
    public void sendFile(String localFilePath, String remoteFilePath)
        throws Exception {
        String remoteTargetDir = remoteFilePath.substring(0, remoteFilePath
            .lastIndexOf("/") + 1);
        String remoteTargetName = remoteFilePath.substring(remoteTargetDir
            .length());
        if (nbChannel == 9) {
            nbChannel = 0;
            reconnect();
        }
        nbChannel++;
        scp.put(localFilePath, remoteTargetDir, remoteTargetName, "0777");
    }

    /**
     * Get files 
     * @param remotePath
     * @param localDestinationPath
     * @throws Exception 
     * @throws IOException 
     */
    public List<String> getResultsFiles(String remotePath,
        String localDestinationPath) throws Exception {
        List<String> filesPaths = new ArrayList<String>();
        // To ensure well connection
        reconnect();
        // List files
        String list = sendShell("ls " + remotePath);
        if (list != null) {
            if (list.indexOf(CMD_INVITE) != -1) {
                list = list.substring(list.indexOf(CMD_INVITE)
                    + CMD_INVITE.length());
            }
            if (list.indexOf("not found") != -1) {
                throw new Exception(
                    "No output files!");
            }
            List<String> files = getFilesList(list);
            if (files.size() > 0) {
                File tmp = null;
                for (String f : files) {
                    tmp = new File(localDestinationPath, f);
                    if (tmp.exists()) {
                        tmp.delete();
                    }
                    if (nbChannel == 9) {
                        nbChannel = 0;
                        reconnect();
                    }
                    nbChannel++;
                    String absPath = tmp.getAbsolutePath();
                    filesPaths.add(absPath);
                    scp.get(remotePath + f, absPath);
                }
                return filesPaths;
            } else {
                throw new Exception(
                    "No output files!");
            }
        } else {
            throw new Exception(
                "Impossible to retreive files list!");
        }
    }

    /**
     * Compute file list received from server ("ls" command) to a list of files
     * @param lsResult
     * @return
     */
    private List<String> getFilesList(String lsResult) {
        List<String> files = new ArrayList<String>();
        String[] tabl = lsResult.split("\\n");
        for (String s : tabl) {
            s = s.trim();
            if (!"".equals(s)) {
                if (s.indexOf(" ") == -1) {
                    files.add(s);
                } else {
                    String[] tabl2 = s.split(" ");
                    for (String s2 : tabl2) {
                        s2 = s2.trim();
                        if (!"".equals(s2)) {
                            files.add(s2);
                        }
                    }
                }
            }
        }
        return files;
    }

    /**
     * Move command shell to specified directory
     * @param path
     * @throws Exception
     */
    public void moveToDir(String path) throws Exception {
        sendShell("cd " + path);
    }

    /**
     * Extract the integers value from a string
     * Supporting method used to get the port number for epsv mode
     * @param str
     * @return
     */
    @SuppressWarnings("unused")
	private static String getOnlyNumerics(String str) {

        if (str == null) {
            return null;
        }
        StringBuffer strBuff = new StringBuffer();
        char c;
        for (int i = 3; i < str.length(); i++) {
            c = str.charAt(i);
            if (Character.isDigit(c)) {
                strBuff.append(c);
            }
        }
        return strBuff.toString();
    }
    
    public String getHead() {
		return head;
	}

	public void setHead(String head) {
		this.head = head;
	}
	
	public String getPath() {
		return path;
	}

	public void setPath(String path) {
		this.path = path;
	}
	
    /**
     * Local class that implements logging credentials
     */
    private static class MyUserInfo implements UserInfo {

        private String password;

        public void setPassword(String password) {
            this.password = password;

        }

        public String getPassphrase() {
            return null;
        }

        public String getPassword() {
            return password;
        }

        public boolean promptPassword(String arg0) {
            return true;
        }

        public boolean promptPassphrase(String arg0) {
            return true;
        }

        public boolean promptYesNo(String arg0) {
            return true;
        }

        public void showMessage(String arg0) {
            System.out.println(arg0);
        }
    }
}